package com.hanlink.dsp.ui.activities;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;

import com.hanlink.dsp.BtDspApplication;
import com.hanlink.dsp.DspSettings;
import com.hanlink.dsp.model.UploadThread;
import com.hanlink.dsp.model.UserProfile;
import com.hanlink.dsp.protocols.DeviceProtocol;
import com.hanlink.dsp.protocols.ParseDataProtocolUtil;
import com.hanlink.dsp.util.DataUtil;
import com.qztech.bluetooth.BluetoothClientManager;
import com.qztech.bluetooth.ZBtDevice;
import com.qztech.bluetooth.event.NotifyDataReadCompleteEvent;
import com.qztech.sdk.data.Resource;
import com.qztech.sdk.model.ArchViewModel;
import com.qztech.sdk.utils.BLog;
import com.qztech.sdk.utils.ByteUtil;
import com.qztech.utils.YzDebug;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.xutils.common.util.IOUtil;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import io.reactivex.Flowable;
import io.reactivex.Observable;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

/**
 * @author : zhanghb
 * @date : 2019/1/25
 * @email : 2573475062@qq.com
 **/
public class HomeViewModel extends ArchViewModel {
    private final static String TAG = "HomeViewModel";
    public MutableLiveData<Resource<Boolean>> mParseLiveData = new MutableLiveData<>();
    private BluetoothClientManager mBluetoothClientManager;
    private UploadThread mUploadThread;
    private Disposable mReadDataDisposable;
    private Disposable mTimeoutDisposable;
    private int mRetryTimes;
    private final static int READ_MAX_TIMES = 10;

    public HomeViewModel() {
        mBluetoothClientManager = BluetoothClientManager.getInstance(BtDspApplication.getInstance());
        mBluetoothClientManager.setReadData(false);
        EventBus.getDefault().register(this);
    }

    public void loadData() {
        DataUtil.loadData();
    }

    public ZBtDevice getConnectedDevice() {
        return mBluetoothClientManager.getConnectedDevice();
    }

    public boolean isBluetoothOpen() {
        return mBluetoothClientManager.isBluetoothOpened();
    }

    public void openBluetooth() {
        mBluetoothClientManager.openBluetooth();
    }

    public void searchBluetooth() {
        mBluetoothClientManager.stopSearch();
        mBluetoothClientManager.searchBleDevice();
    }

    public void connect(String mac, String name) {
        mBluetoothClientManager.setReadData(false);
        ZBtDevice zBtDevice = new ZBtDevice();
        zBtDevice.setMac(mac);
        zBtDevice.setName(name);
        mBluetoothClientManager.connectLeDevice(zBtDevice);
    }

    public void cancelSearch() {
        mBluetoothClientManager.stopSearch();
    }

    public void disconnect() {
        mBluetoothClientManager.disconnect();
    }

    public void cancelReadData() {
        mBluetoothClientManager.setReadData(false);
        if (mReadDataDisposable != null && !mReadDataDisposable.isDisposed()) {
            mReadDataDisposable.dispose();
        }
    }

    @SuppressLint("CheckResult")
    public void parseShareFile(Uri contentUri) {
        mParseLiveData.postValue(Resource.loading());
        Observable.create((ObservableOnSubscribe<Boolean>) emitter -> {
            InputStream inputStream = null;
            FileOutputStream fileOutputStream = null;
            File file = null;
            try {
                inputStream = BtDspApplication.getInstance().getContentResolver().openInputStream(contentUri);
                file = new File(BtDspApplication.getInstance().getExternalCacheDir() + "/" + UUID.randomUUID().toString());
                file.createNewFile();
                fileOutputStream = new FileOutputStream(file);
                byte[] buffer = new byte[1024];
                int len;
                while ((len = inputStream.read(buffer)) != -1) {
                    fileOutputStream.write(buffer, 0, len);
                }
                fileOutputStream.flush();
            } catch (IOException e) {
                YzDebug.d("parseShareFile", e);
            } finally {
                IOUtil.closeQuietly(inputStream);
                IOUtil.closeQuietly(fileOutputStream);
            }
            FileReader fileReader = new FileReader(file);
            BufferedReader reader = new BufferedReader(fileReader);
            String cmd;
            DspSettings.updateUserProfile(DspSettings.DEFAULT_USERP_PROFILE);
            DataUtil.resetDefaultAppData();//加载默认的数据、主要是加载出相应的ID
            while ((cmd = reader.readLine()) != null) {
                if (TextUtils.isEmpty(cmd))continue;
                YzDebug.d("share read:"+ cmd);

                if (!cmd.startsWith("aa55") && !cmd.startsWith("AA55") && !cmd.startsWith("aa8")) {
                    reader.close();
                    emitter.onError(new IllegalAccessError("file error"));
                    return;
                }
                ParseDataProtocolUtil.parse(ByteUtil.hexToBytes(cmd.replace("aa55", "")));
            }
            reader.close();
            emitter.onNext(true);
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(aBoolean -> {
                    startUpload();
                    mParseLiveData.postValue(Resource.success(true));
                }, e -> {
                    e.printStackTrace();
                    mParseLiveData.postValue(Resource.error(e));
                });
    }

    /**
     * 上传
     */
    public void readData() {
        cancelReadData();
        mParseLiveData.postValue(Resource.loading());
        mReadDataDisposable = Schedulers.io().scheduleDirect(() -> {
            mRetryTimes = 0;
            read();
        });
    }

    private void read() {
        mBluetoothClientManager.setReadData(true);
        ParseDataProtocolUtil.init();
        ParseDataProtocolUtil.readData(0);
        setReadTimeout();
        mBluetoothClientManager.write(DeviceProtocol.readData(0));
    }

    /**
     * 上传超时
     */
    private void setReadTimeout() {

        cancelTimeout();
        YzDebug.d("setReadTimeout-------------");

//        mTimeoutDisposable = Flowable.timer(3, TimeUnit.SECONDS)
        mTimeoutDisposable = Flowable.interval(3, TimeUnit.SECONDS)
                .observeOn(Schedulers.io())
                .subscribe(aLong -> {
                    boolean parsed = ParseDataProtocolUtil.parseData();
                    YzDebug.d("setReadTimeout check...:"+ mRetryTimes +"  " + parsed);
                    if (parsed) {
                        onReadComplete();
                        return;
                    }
                    if (mRetryTimes < READ_MAX_TIMES) {
                        if (mRetryTimes % 3 == 2)
                        {
                            read();
                        }
                        mRetryTimes++;
                        return;
                    }
                    cancelReadData();
                    mParseLiveData.postValue(Resource.error(new RuntimeException("read timeout")));
                }, e -> {
                    mParseLiveData.postValue(Resource.error(e));
                });
    }

    private void cancelTimeout() {
        YzDebug.d("cancelTimeout----------", new Throwable());
        if (mTimeoutDisposable != null && !mTimeoutDisposable.isDisposed()) {
            mTimeoutDisposable.dispose();
        }
    }

    @Subscribe(threadMode = ThreadMode.BACKGROUND)
    public void onNotifyEvent(NotifyDataReadCompleteEvent event) {
        //yangzhong  2023年8月18日 00:42:42
       /* cancelTimeout();
        YzDebug.d("onNotifyEvent:"+mBluetoothClientManager.isReadData());
        if (!mBluetoothClientManager.isReadData()) return;

        int index = ParseDataProtocolUtil.getReadDataIndex();
        YzDebug.d("onNotifyEvent index:" + index);
        if (index == 0) {
            onReadComplete();
        } else if (index == 1) {
        }*/
    }
    private void onReadComplete() {
        YzDebug.d("-------------------onReadComplete");
        cancelTimeout();
        DspSettings.updateUserProfile(DspSettings.DEFAULT_USERP_PROFILE);
        DataUtil.resetDefaultAppData();
        ParseDataProtocolUtil.parseAll();
        BLog.d(TAG, "数据读取完成");
        mRetryTimes = 0;
        mBluetoothClientManager.setReadData(false);
        mParseLiveData.postValue(Resource.success(true));
    }

    public void resetApp() {
        mBluetoothClientManager.write(DeviceProtocol.resetApp());
        DspSettings.updateUserProfile(DspSettings.DEFAULT_USERP_PROFILE);
        DataUtil.resetDefaultAppData();
        DspSettings.reset = true;

    }

    @Override
    protected void onCleared() {
        super.onCleared();
        EventBus.getDefault().unregister(this);
//        mBluetoothClientManager.disconnect();
    }

    public void startUpload() {
        stopUpload();
        this.mUploadThread = new UploadThread();
        this.mUploadThread.start();
    }

    private void stopUpload() {
        if ((this.mUploadThread != null) && (!this.mUploadThread.isInterrupted())) {
            this.mUploadThread.interrupt();
        }
    }


    private String mLastConnectedDevice;
    public void sageLastConnectDevice(String mac) {
        mLastConnectedDevice = mac;
        YzDebug.d("sageLastConnectDevice:"+ mac);
        SharedPreferences sharedPreferences = BtDspApplication.getInstance().getSharedPreferences("device_config_info", Context.MODE_PRIVATE);
        if (mac == null) sharedPreferences.edit().clear().apply();
        else sharedPreferences.edit().putString("mac", mac).apply();
    }

    public String getLastConnectedDevice() {
        if (mLastConnectedDevice == null) {
            SharedPreferences sharedPreferences = BtDspApplication.getInstance().getSharedPreferences("device_config_info", Context.MODE_PRIVATE);
            mLastConnectedDevice = sharedPreferences.getString("mac", null);
        }
        YzDebug.d("getLastConnectedDevice:" + mLastConnectedDevice);
        return mLastConnectedDevice;
    }
}
